package com._13read.rss.manager.impl;

import com._13read.rss.entity.RssEntry;
import com._13read.rss.entity.RssFeed;
import com._13read.rss.entity.RssLog;
import com._13read.rss.entity.RssSource;
import com._13read.rss.manager.IRssManager;
import com._13read.rss.service.IRssEntryService;
import com._13read.rss.service.IRssFeedService;
import com._13read.rss.service.IRssLogService;
import com._13read.rss.service.IRssSourceService;
import com._13read.rss.util.LocalDateTimeUtil;
import com._13read.rss.util.RssUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.rometools.rome.feed.synd.SyndContent;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import com.rometools.rome.feed.synd.SyndImage;
import com.rometools.rome.io.FeedException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class RssManagerImpl implements IRssManager {

    @Autowired
    private IRssLogService rssLogService;
    @Autowired
    private IRssSourceService rssSourceService;
    @Autowired
    private IRssFeedService rssFeedService;
    @Autowired
    private IRssEntryService rssEntryService;

    @Transactional
    @Override
    public void addSource(String urlString) {
        RssSource bySource = rssSourceService.bySource(urlString);
        if (null != bySource) return;
        SyndFeed syndFeed = null;
        // todo 异常处理
        try {
            syndFeed = RssUtil.getSyndFeed(urlString);
        } catch (IOException e) {
            log.error("解析feed异常",e);
            return;
        } catch (FeedException e) {
            log.error("解析feed异常",e);
            return;
        }
        if (null == syndFeed){
            log.error("解析feed异常,{}","feed null");
            return;
        }
        RssSource rssSource = new RssSource();
        rssSource.setId(IdWorker.getId());
        rssSource.setCreateTime(LocalDateTime.now());
        rssSource.setSource(urlString);
        rssSource.setDescription(syndFeed.getDescription());
        rssSource.setLink(syndFeed.getLink());
        SyndImage image = syndFeed.getImage();
        if (null != image) {
            rssSource.setLogo(syndFeed.getImage().getUrl());
        }else {
            rssSource.setLogo("");
        }
        rssSource.setTitle(syndFeed.getTitle());
        rssSource.setIsDelete(0);
        rssSourceService.save(rssSource);
        // 解析
        this.parse2db(rssSource);
    }

    @Transactional
    @Override
    public void parse2db(RssSource rssSource) {
        LocalDateTime now = LocalDateTime.now();
        String source = rssSource.getSource();
//        String rssXmlString = RssUtil.getRssXmlString(source);
        SyndFeed syndFeed = null;
        // todo 异常处理
        try {
            syndFeed = RssUtil.getSyndFeed(source);
        } catch (IOException e) {
            log.error("解析feed异常",e);
            return;
        } catch (FeedException e) {
            log.error("解析feed异常",e);
            return;
        }
        if (null == syndFeed){
            log.error("解析feed异常,{}","feed null");
            return;
        }
        String feedText = JSONObject.toJSONString(syndFeed);
        RssLog byRssSourceIdLastOne = rssLogService.byRssSourceIdLastOne(rssSource.getId());
        if (null != byRssSourceIdLastOne) {
            if (byRssSourceIdLastOne.getFeedHashCode() == feedText.hashCode()) return;
        }
        RssFeed rssFeed = new RssFeed();
        rssFeed.setId(IdWorker.getId());
        rssFeed.setCreateTime(now);
        rssFeed.setRssSourceId(rssSource.getId());
        rssFeed.setFeedText(feedText);
        rssFeed.setIsDelete(0);
        rssFeedService.save(rssFeed);
        if (null == syndFeed){
            throw new RuntimeException();
        }
        List<SyndEntry> entries = RssUtil.getEntries(syndFeed);
        for (SyndEntry entry : entries){
            RssEntry rssEntry = new RssEntry();
            rssEntry.setCreateTime(now);
            rssEntry.setRssSourceId(rssSource.getId());
            rssEntry.setRssFeedId(rssFeed.getId());
            rssEntry.setLink(entry.getLink());
            rssEntry.setTitle(entry.getTitle());
            rssEntry.setAuthor(entry.getAuthor());
            Date publishedDate = entry.getPublishedDate();
            if (null != publishedDate){
                rssEntry.setPubDate(LocalDateTimeUtil.date2LocalDateTime(entry.getPublishedDate()));
            }
            rssEntry.setDescription(entry.getDescription().getValue());
            rssEntry.setIsDelete(0);
            List<SyndContent> contents = entry.getContents();
            for (SyndContent content :contents){
                String value = content.getValue();
                if (StringUtils.isEmpty(rssEntry.getContent())){
                    rssEntry.setContent(value);
                }else {
                    rssEntry.setContent(rssEntry.getContent() + value);
                }

            }
            rssEntryService.save(rssEntry);
        }
        RssLog rssLog = new RssLog();
        rssLog.setCreateTime(now);
        rssLog.setRssFeedId(rssFeed.getId());
        rssLog.setRssSourceId(rssSource.getId());
        rssLog.setFeedHashCode(feedText.hashCode());
        rssLog.setIsDelete(0);
        rssLogService.save(rssLog);
    }

    @Transactional
    @Override
    public void parse2db(Long rssSourceId) {
        RssSource byId = rssSourceService.getById(rssSourceId);
        if (null == byId) return;
        this.parse2db(byId);
    }
}
